import { test } from '@playwright/test';

import type { Application } from '../models/application';
import { appConfigs } from '../presets';
import type { FakeUser } from '../testUtils';
import { createTestUtils } from '../testUtils';

test.describe('session tasks eject flow @nextjs', () => {
  test.describe.configure({ mode: 'serial' });
  let app: Application;
  let user: FakeUser;

  test.beforeAll(async () => {
    test.setTimeout(90_000); // Wait for app to be ready
    app = await appConfigs.next.appRouter
      .clone()
      .addFile(
        'src/app/provider.tsx',
        () => `'use client'
import { ClerkProvider } from "@clerk/nextjs";

export function Provider({ children }: { children: any }) {
return (
  <ClerkProvider taskUrls={{ 'choose-organization': '/onboarding/choose-organization' }}>
    {children}
  </ClerkProvider>
)
}`,
      )
      .addFile(
        'src/app/layout.tsx',
        () => `import './globals.css';
import { Inter } from 'next/font/google';
import { Provider } from './provider';

const inter = Inter({ subsets: ['latin'] });

export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
  <Provider>
    <html lang='en'>
      <body className={inter.className}>{children}</body>
    </html>
  </Provider>
);
}`,
      )
      .addFile(
        'src/app/onboarding/choose-organization/page.tsx',
        () => `
import { TaskChooseOrganization } from '@clerk/nextjs';

export default function Page() {
return (
  <TaskChooseOrganization redirectUrlComplete='/'/>
);
}`,
      )
      .commit();

    await app.setup();
    await app.withEnv(appConfigs.envs.withSessionTasks);
    await app.dev();

    const u = createTestUtils({ app });
    user = u.services.users.createFakeUser();
    await u.services.users.createBapiUser(user);
  });

  test.afterAll(async () => {
    const u = createTestUtils({ app });
    await user.deleteIfExists();
    await u.services.organizations.deleteAll();
    await app.teardown();
  });

  test.afterEach(async ({ page, context }) => {
    const u = createTestUtils({ app, page, context });
    await u.page.signOut();
    await u.page.context().clearCookies();
  });

  test('redirects to completion page after resolving task', async ({ page, context }) => {
    const u = createTestUtils({ app, page, context });

    // Performs sign-in
    await u.po.signIn.goTo();
    await u.po.signIn.setIdentifier(user.email);
    await u.po.signIn.continue();
    await u.po.signIn.setPassword(user.password);
    await u.po.signIn.continue();
    await u.po.expect.toBeSignedIn();

    // Complete the organization selection task
    await u.page.waitForAppUrl('/onboarding/choose-organization');
    const fakeOrganization = Object.assign(u.services.organizations.createFakeOrganization(), {
      slug: u.services.organizations.createFakeOrganization().slug + '-eject-flow',
    });
    await u.po.sessionTask.resolveForceOrganizationSelectionTask(fakeOrganization);
    await u.po.expect.toHaveResolvedTask();

    // Verify redirect to completion page
    await u.page.waitForAppUrl('/');
  });
});
